<?php

// input types
define('FRM_TEXT'			,1);
define('FRM_TEXTAREA'	,2);
define('FRM_SELECT'		,3);
define('FRM_RADIO'		,4);
define('FRM_CHECKBOX'	,5);
define('FRM_PASSWORD'	,6);
define('FRM_FILE'			,7);
define('FRM_HIDDEN'		,8);

//common regexps
define('REGEXP_EMAIL'	,'^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*.([a-z]{2,3})$');

/**
 * Form item
 *
 */
class FormItem
{
	public $name;
	public $type;
	public $regexp;
	public $value;
	public $label;
	public $options = Array();
	public $mandatory = false;
	public $error = false;
	public $error_msg = '';
	public $class = '';
	public $db_column = '';
	public $db_id = false;
	public $hash = false;
	public $sameas = '';
	public $minlen = 0;

	/**
	 * Constructor
	 */
	function __construct($name,$type,$regexp,$value = '',$label)
	{
		$this->name = $name;
		$this->type = $type;
		$this->regexp = $regexp;
		$this->value = $value;
		$this->label = $label;

		return $this;
	}

	/**
	 * FormItem::validate()
	 * Validate item
	 * @param string $fields
	 * @return
	 */
	public function validate($fields)
	{
		if(strlen($this->regexp) > 0 && !preg_match($this->regexp,$this->value))
		{
			$this->error = true;
			$this->error_msg = 'This field does not match specified format!';
		}
		elseif($this->mandatory && strlen($this->value) < 1)
		{
			//echo 'Chyba! hodnota: ',$this->value;
			$this->error = true;
			$this->error_msg = 'This field is mandatory!';
		}
		elseif($this->sameas && $this->value != $fields[$this->sameas]->value)
		{
			$this->error = true;
			$this->error_msg = 'This field does not match field "'.$fields[$this->sameas]->label.'"!';
		}
		elseif(strlen($this->value) < $this->minlen)
		{
			$this->error = true;
			$this->error_msg = 'This field must be at least '.$this->minlen.' chars long!';
		}
		else $this->error = false;

		return ($this->error == true) ? false : true;
	}
}

/**
 * Form
 *
 * @package
 * @author kubicek
 * @copyright Copyright (c) 2010
 * @version $Id$
 * @access public
 */
class Form
{
	private $name; //name of form
	private $fields = Array(); // array for FormItem objects
	private $multipart = false; //is this form multipart => upload file
	private $method; //method for submit[POST|GET]
	public $sended = false; //was form send?
	public $plugin; //plugin to call for processing form
	public $action; //action on $plugin for processing form
	public $error = false; //was there any error?
	public $db_table; //table for insert
	public $db_insert = false; //insert form data to db?
	public $db_update = false; //should we update values in DB?
	public $succ_url = ''; //where to go, if frm handle is success

	/**
	 * Constructor
	 */
	function __construct($name,$method = 'POST')
	{
		global $db;
		$this->db = $db;

		if(isset($_SESSION['yapsform_'.$name])) //is there any form in session with this name?
		{
			$temp = Form::load($name); //load it

			if($temp->sended) //should we load it?
			{
				$this->name = $temp->name;
				$this->fields = $temp->fields;
				$this->multipart = $temp->multipart;
				$this->method = $temp->method;
				$this->plugin = $temp->plugin;
				$this->action = $temp->action;
				$this->error = $temp->error;
				$this->db_table = $temp->db_table;
				$this->db_insert = $temp->db_insert;
				$this->succ_url = $temp->succ_url;
				$this->db_update = $temp->db_update;

				$this->loaded = true; //dont accept any input from php code
				$this->sended = false;
			}
			else //create brand new form
			{
				$this->name = $name;
				$this->method = $method;
				$this->loaded = false;

				$this->addHidden('frm_name',$name);
			}
		}
		else //there is no form in session, create brand new form
		{
			$this->name = $name;
			$this->method = $method;
			$this->loaded = false;

			$this->addHidden('frm_name',$name);
		}
	}

	/**
	 * Form::register_handler()
	 * Register handler for processing this form
	 * @param mixed $plugin
	 * @param mixed $action
	 * @return
	 */
	public function register_handler($plugin,$action)
	{
		if(!$this->loaded)
		{
			$this->action = $action;
			$this->plugin = $plugin;
			$this->save();
		}
	}

	/**
	 * Form::default_handler()
	 * Handle this form with default handler, WEB_URL will be added before $succ_url
	 * @param mixed $suc_url
	 * @return
	 */
	public function use_default_handler($succ_url)
	{
		if(!$this->loaded)
		{
			$this->plugin = 'core_form';
			$this->succ_url = $succ_url;
			$this->save();
		}
	}

	/**
	 * Form::field()
	 * Get or set a value in form. If you try to set value to non-existing field, it will be created with given $name
	 * @param mixed $name
	 * @param string $value
	 * @return
	 */
	public function field($name, $value = '')
	{
		if(strlen($value) > 0)
		{
			$this->fields[$name] = new FormItem($name,FRM_TEXT,'',$value,'');
			$this->save();
		}
		else return $this->fields[$name]->value;
	}

	/**
	 * Form::jquery_validation()
	 * Enable validation with jQuery
	 * @return
	 */
	public function jquery_validation()
	{
		$this->jquery_validation = true;
	}

	/**
	 * Form::save()
	 * Save form in serialized form to session
	 * @return
	 */
	public function save()
	{
		$_SESSION['yapsform_'.$this->name] = serialize($this);
	}

	/**
	 * Form::load()
	 * Load form with name $name from session
	 * @param mixed $name
	 * @return
	 */
	public function load($name)
	{
		$form = unserialize($_SESSION['yapsform_'.$name]);
		return $form;
	}

	/**
	 * Form::remove()
	 * Remove stored form from session
	 * @return
	 */
	public function remove()
	{
		unset($_SESSION['yapsform_'.$this->name]);
	}

	/**
	 * Form::process()
	 * Process this form calling plugin and function as specified by register_handler
	 * @return
	 */
	public function process()
	{
		global $core;

		$this->sended = true;
		$this->save();


		if($this->plugin == 'core_form')
		{
			$this->frm_handle();
		}
		else
		{
			$name = $this->action;
			$plugin = $core->load_plugin($this->plugin);
			$plugin->$name($this->name);
		}
	}

	/**
	 * Form::frm_handle()
	 * Default form handler, it only inserts data to DB
	 * @param mixed $name
	 * @return
	 */
	private function frm_handle()
	{
		global $core,$theme;

		$theme->render = false;
		$form = $this;
		$form->update();
		if(!$form->error)
		{
			if($form->db_insert) //we will insert data from form to db
			{
				$form->insert_to_db();
				if($form->error) $form->return_back();
			}
			elseif($form->db_update)
			{
				$form->update_in_db();
				if($form->error) $form->return_back();
			}

			$form->remove();
			$core->refresh_header($form->succ_url);
		}
		else
		{
			$form->return_back();
		}
	}

	/**
	 * Form::update()
	 * Update form from [POST|GET]
	 * @return
	 */
	public function update()
	{
		global $core;

		$this->error = false;
		foreach ($this->fields as $name=>$item)
		{
			/*echo 'beru field: '.$name.'<br />';
			$this->print_values();
			echo '----------------------------<br />';*/

			//determine method
			if($this->method == 'POST') $item->value = $core->post_hsc($name);
			else $item->value = $core->get_hsc($name);

			if($item->type == FRM_CHECKBOX && $item->value == 'on') $item->value = 1;

			$this->fields[$name] = $item; //put it back
		}

		//lets validate em
		foreach ($this->fields as $name=>$item)
		{
			$res = $item->validate($this->fields); //validate item using regexp or mandatory check
			if(!$res) $this->error = true;

			$this->fields[$name] = $item; //put it back
		}

		$this->save();
	}

	///////////////////////////
	//	CHECK FUNCTIONS
	///////////////////////////

	/**
	 * Form::mandatory()
	 * Set input to be mandatory
	 * @param mixed $item_name
	 * @return
	 */
	public function mandatory($item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->mandatory = true; //set mandatory to last used field
			else $this->fields[$item_name]->mandatory = true;
			//$this->last_field = $item_name;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::hash_this()
	 * Set input to be hashed by core md5 function
	 * @param string $item_name
	 * @return
	 */
	public function hash_this($item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->hash = true; //set mandatory to last used field
			else $this->fields[$item_name]->hash = true;
			//$this->last_field = $item_name;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::regexp()
	 * Set input to be validated by regexp
	 * @param mixed $regexp
	 * @param string $item_name
	 * @return
	 */
	public function regexp($regexp, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->regexp = $regexp; //set mandatory to last used field
			else $this->fields[$item_name]->regexp = $regexp;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::sameas()
	 * Validation will compare this input with $same_item
	 * @param mixed $same_item
	 * @param string $item_name
	 * @return
	 */
	public function sameas($same_item, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->sameas = $same_item; //set mandatory to last used field
			else $this->fields[$item_name]->sameas = $same_item;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::minlen()
	 * Validate item for minimal length
	 * @param mixed $len
	 * @param string $item_name
	 * @return
	 */
	public function minlen($len, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->minlen = $len; //set mandatory to last used field
			else $this->fields[$item_name]->minlen = $len;
			$this->save();
		}
		return $this;
	}

	////////////////////////////////
	//	END OF CHECK FUNCTIONS
	////////////////////////////////

	/**
	 * Form::db_table()
	 * Set table for form values
	 * @param mixed $table
	 * @return
	 */
	public function db_table($table)
	{
		global $core,$db;

		if(!$this->loaded)
		{
			if(!$db->query("DESCRIBE `$table`")) $core->err("Table $table does not exist!");
			else
			{
				$this->db_table = $table;
				$this->db_insert = true;
				$this->save();
			}
		}
		return $this;
	}

	public function db_update($table)
	{
		global $core,$db;

		if(!$this->loaded)
		{
			if(!$db->query("DESCRIBE `$table`")) $core->err("Table $table does not exist!");
			else
			{
				$this->db_table = $table;
				$this->db_update = true;
				$this->save();
			}
		}
		return $this;
	}

	/**
	 * Form::dbcolumn()
	 * Link DB column to form input
	 * @param mixed $col
	 * @param string $item_name
	 * @return
	 */
	public function dbcol($col, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->db_column = $col; //set class to last used field
			else $this->fields[$item_name]->db_column = $col;
			//$this->last_field = $item_name;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::dbid()
	 * Link DB column with table PK to form input
	 * @param mixed $col
	 * @param string $item_name
	 * @return
	 */
	public function dbid($col, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0)
			{
				$this->fields[$this->last_field]->db_id = true; //set to last used field
				$this->fields[$this->last_field]->db_column = $col;
			}
			else
			{
				$this->fields[$item_name]->db_id = true;
				$this->fields[$item_name]->db_column = $col;
			}

			$this->save();
		}
		return $this;
	}

	/**
	 * Form::insert_to_db()
	 * Insert data from form fields to DB
	 * @return
	 */
	public function insert_to_db()
	{
		global $db,$core;

		foreach ($this->fields as $name=>$item)
		{
			if(strlen($item->db_column) > 0)
			{
				if($item->hash && strlen($item->value) > 0) $item->value = $core->md5($item->value);
				$fields .= '`'.$item->db_column.'` = "'.$item->value.'",';
			}
		}
		$fields = substr($fields,0,-1); //remove last ,

		$res = $db->query("INSERT INTO `$this->db_table` SET $fields");
		if($res) $core->msg('Data from form has been successfully inserted.');
		else
		{
			$core->err('Error when inserting data from form. This is permanent, sorry. Contanct admin please.');
			$form->error = true;
		}
	}

	public function update_in_db()
	{
		global $db,$core;

		foreach ($this->fields as $name=>$item)
		{
			if(strlen($item->db_column) > 0 && $item->db_id != true && strlen($item->value) > 0)
			{
				if($item->hash && strlen($item->value) > 0) $item->value = $core->md5($item->value);
				$fields .= '`'.$item->db_column.'` = "'.$item->value.'",';
			}
			elseif($item->db_id == true) $where = '`'.$item->db_column.'` = "'.$item->value.'"';
		}
		$fields = substr($fields,0,-1); //remove last ,

		$res = $db->query("UPDATE `$this->db_table` SET $fields WHERE $where");
		if($res) $core->msg('Data from form has been successfully updated.');
		else
		{
			$core->err('Error when updating data from form. This is permanent, sorry. Contanct admin please.');
			$form->error = true;
		}
	}

	/**
	 * Form::process_upload()
	 * Process upload of file
	 * @param mixed $name
	 * @param mixed $location
	 * @param mixed $newname
	 * @return
	 */
	public function process_upload($name,$location,$newname = false)
	{
		$file = $_FILES[$name]['tmp_name'];
		$filename = $_FILES[$name]['name'];

		if($newname) $filename = $newname;

		move_uploaded_file($file,$location.$filename);

		return $filename;
	}

	/**
	 * Form::return_back()
	 * Return back to form page
	 * @return
	 */
	public function return_back()
	{
		global $core,$theme;

		$this->save();

		//$core->refresh_header($_SESSION['plugin'].'-'.$_SESSION['action']); //refresh page to form page
		$where = substr($_SERVER['HTTP_REFERER'],strlen(WEB_URL),strlen($_SERVER['HTTP_REFERER']) - strlen(WEB_URL));
		$core->refresh_header($where,1); //refresh page to form page

	}

	/**
	 * Form::cssclass()
	 * Add class to form field
	 * @param mixed $class
	 * @param string $item_name
	 * @return
	 */
	public function cssclass($class, $item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0) $this->fields[$this->last_field]->class = $class; //set class to last used field
			else $this->fields[$item_name]->class = $class;
			//$this->last_field = $item_name;
			$this->save();
		}
		return $this;
	}

	/**
	 * Form::add()
	 * Add new item to form
	 * @param mixed $name name of item
	 * @param mixed $type type, you can use defines, for example FRM_TEXT
	 * @param mixed $regexp regexp for validation
	 * @param mixed $value default value
	 * @return
	 */
	public function add($name,$type,$label = '',$value = '',$regexp = '')
	{
		if(!$this->loaded)
		{
			//echo 'Vkladam input jmenem "'.$name.'" ktery je typu '.$type.'<br />';
			if($type == FRM_FILE) $this->multipart = true;

			$this->fields[$name] = new FormItem($name,$type,$regexp,$value,$label);
			$this->last_field = $name;
			$this->save();
		}

		return $this;
	}

	/**
	 * Form::addText()
	 * Symlink for add with FRM_TEXT
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addText($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_TEXT,$label,$value,$regexp);
	}

	/**
	 * Form::addText()
	 * Symlink for add with FRM_TEXT
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addHidden($name,$value = '',$regexp = '')
	{
		return $this->add($name,FRM_HIDDEN,$name,$value,$regexp);
	}

	/**
	 * Form::addTextarea()
	 * Symlink for add with FRM_TEXTAREA
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addTextarea($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_TEXTAREA,$label,$value,$regexp);
	}

	/**
	 * Form::addCheckbox()
	 * Symlink for add with FRM_CHECKBOX
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addCheckbox($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_CHECKBOX,$label,$value,$regexp);
	}

	/**
	 * Form::addRadio()
	 * Symlink for add with FRM_RADIO
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addRadio($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_RADIO,$label,$value,$regexp);
	}

	/**
	 * Form::addSelect()
	 * Symlink for add with FRM_SELECT
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addSelect($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_SELECT,$label,$value,$regexp);
	}

	/**
	 * Form::addPassword()
	 * Symlink for add with FRM_PASSWORD
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addPassword($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_PASSWORD,$label,$value,$regexp);
	}

	/**
	 * Form::addFile()
	 * Symlink for add with FRM_FILE
	 * @param mixed $name
	 * @param string $label
	 * @param string $value
	 * @param string $regexp
	 * @return
	 */
	public function addFile($name,$label = '',$value = '',$regexp = '')
	{
		return $this->add($name,FRM_FILE,$label,$value,$regexp);
	}

	/**
	 * Form::add_option()
	 * Add option to input like select or radio buttons
	 * @param mixed $item_name
	 * @param mixed $name
	 * @param mixed $value
	 * @return
	 */
	public function add_option($name,$value,$item_name = '')
	{
		if(!$this->loaded)
		{
			if(strlen($item_name) == 0)	$this->fields[$this->last_field]->options[$name] = $value; //set option to last used field
			else
			{
				$this->fields[$item_name]->options[$name] = $value;
				//$this->last_field = $item_name;
			}

			$this->save();
		}
		return $this;
	}

	/**
	 * Form::add_options()
	 * If you are lazy, you can insert whole array of options, specified like
	 * Array([option_value] => option_text)
	 * @param mixed $item_name
	 * @param mixed $array
	 * @return
	 */
	public function add_options($array,$item_name = '')
	{
		if(!$this->loaded)
		{
			foreach ($array as $key=>$value)
			{
				if(strlen($item_name) == 0) $this->add_option($key,$value,$this->last_fields);
				else $this->add_option($key,$value,$item_name);
			}

			$this->save();
		}

		return $this;
	}

	/**
	 * Form::add_options_from_db()
	 * Add options from DB query
	 * @param mixed $query Example: <option value="value">text</option> | Select id as value, name as text from `aaa`
	 * @param string $item_name
	 * @return
	 */
	public function add_options_from_db($query,$item_name = '')
	{
		if(!$this->loaded)
		{
			$rows = $this->db->get_rows($query);
			foreach ($rows as $row)
			{
				if(strlen($item_name) == 0) $this->add_option($row['value'],$row['text'],$this->last_fields);
				else $this->add_option($row['value'],$row['text'],$item_name);
			}

			$this->save();
		}

		return $this;
	}

	/**
	 * Form::render_label()
	 * Render label for input
	 * @param mixed $item_name
	 * @return
	 */
	public function render_label($item_name)
	{
		return '<label for="'.$this->name.$item_name.'">'.$this->fields[$item_name]->label.(($this->fields[$item_name]->mandatory == true) ? '*' : '').'</label>';
	}

	/**
	 * Form::render_input()
	 * Render input with given name, determine type of input based on type of input
	 * @param mixed $item_name
	 * @return
	 */
	public function render_input($item_name)
	{
		$item = $this->fields[$item_name];
		ob_start();

		switch($item->type)
		{
			case FRM_TEXT:
				echo '<input type="text" name="'.$item_name.'" value="'.$item->value.'" id="'.$this->name.$item_name.'" class="'.$this->class.'"/>';
			break;

			case FRM_TEXTAREA:
				echo '<textarea name="'.$item_name.'" id="'.$this->name.$item_name.'" class="'.$this->class.'" rows="5" cols="50">'.$item->value.'</textarea>';
			break;

			case FRM_SELECT:
				echo '<select name="'.$item_name.'" id="'.$this->name.$item_name.'" class="'.$this->class.'">';
				foreach ($item->options as $value=>$text)
				{
					if($value == $item->value) $selected = 'selected="selected"';
					else $selected = '';

					echo '<option value="'.$value.'" '.$selected.'>'.$text.'</option>';
				}
				echo '</select>';
			break;

			case FRM_RADIO:
				$i = 0;
				foreach ($item->options as $value=>$text)
				{
					$i++;
					if($item->value == $value) $checked = 'checked="checked"';
					else $checked = '';

					echo '<input type="radio" name="'.$item_name.'" value="'.$value.'" id="'.$this->name.$item_name.$i.'" '.$checked.' class="'.$this->class.'"/>
								<label for="'.$this->name.$item_name.$i.'">'.$text.'</label>';
				}
			break;

			case FRM_PASSWORD:
				echo '<input type="password" name="'.$item_name.'" value="" id="'.$this->name.$item_name.'" class="'.$this->class.'"/>';
				break;

			case FRM_CHECKBOX:
				if($item->value > 0) $checked = 'checked="checked"';
				else $checked = '';

				echo '<input type="checkbox" name="'.$item_name.'" '.$checked.' id="'.$this->name.$item_name.'" class="'.$this->class.'"/>';
				break;

			case FRM_FILE:
				echo '<input type="file" name="'.$item_name.'" id="'.$this->name.$item_name.'" class="'.$this->class.'"/>';
				break;

			case FRM_HIDDEN:
				echo '<input type="hidden" name="'.$item_name.'" value="'.$item->value.'" id="'.$this->name.$item_name.'"/>';
				break;
		}

		if($item->error)
		{
			echo '<div class="frm_error">'.$item->error_msg.'</div>';
			$item->error = false;
		}

		return ob_get_clean();
	}

	public function render_submit($text = 'Odeslat')
	{
		return '<input type="submit" value="'.$text.'" /></form>';
	}

	public function render_form()
	{
		global $theme;

		if($this->multipart) $multipart = 'enctype="multipart/form-data"';

		if($this->jquery_validation)
		{
			$rules = '';
			foreach ($this->fields as $name=>$item)
			{
				if($item->mandatory) $rules .= $name.': "required",';
			}

			$theme->include_validation();
			$theme->js('$("#frm_'.$this->name.'").validate({
			rules:
			{
			'.$rules.'
			},
			highlight: function(element, errorClass)
			{
				$(element).fadeOut(function()
				{
					$(element).fadeIn();
				});
			}});');
		}

		return '<form name="'.$this->name.'" id="frm_'.$this->name.'" method="'.$this->method.'" action="form-process" '.$multipart.'>';
	}

	/**
	 * Form::render()
	 * Rendering form, simple table layout
	 * @return
	 */
	public function render()
	{
		foreach ($this->fields as $name=>$item)
		{
			if($item->type == FRM_HIDDEN) $form_fields .= $this->render_input($name);
			else $form_fields .= '<tr><td>'.$this->render_label($name).'</td><td>'.$this->render_input($name).'</td></tr>';
		}

		if($this->multipart) $multipart = 'enctype="multipart/form-data"';

		echo '<div class="form">
					'.$this->render_form().'
					<table>
					'.$form_fields.'
					</table>
					'.$this->render_submit().'
					</div>';
	}

	public function print_values()
	{
		echo '<table border="1">';
		foreach ($this->fields as $name=>$item)
		{
			echo '<tr><td>',$name,'</td><td>',$item->value,'</td></tr>';
		}
		echo '</table>';
	}

	public function debug()
	{
		var_dump($this);
	}
}

?>